/*

                  写字楼里写字间，写字间里程序员；
                  程序人'猿'写程序，又拿程序换酒钱。
                  酒醒只在网上坐，酒醉还来网下眠；
                  酒醉酒醒日复日，网上网下年复年。
                  但愿老死电脑间，不愿鞠躬老板前；
                  奔驰宝马贵者趣，公交自行程序员。
                  别人笑我忒疯癫，我笑自己命太贱；
                  不见满街漂亮妹，哪个归得程序'猿'？
━━━━━━神兽出没━━━━━━
 ┏┓   ┏┓
┏┛┻━━━┛┻┓
┃       ┃
┃   ━   ┃
┃ ┳┛ ┗┳ ┃
┃       ┃
┃   ┻   ┃
┃       ┃
┗━┓   ┏━┛
  ┃   ┃                    神兽保佑, 永无BUG!
  ┃   ┃       Code is far away from bug with the animal protecting
  ┃   ┗━━━┓
  ┃       ┣┓
  ┃       ┏┛
  ┗┓┓┏━┳┓┏┛
   ┃┫┫ ┃┫┫
   ┗┻┛ ┗┻┛
 */

import vo.pb.UserVo;
import com.google.protobuf.InvalidProtocolBufferException;
import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.*;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document;
import org.bson.types.Binary;

import java.util.ArrayList;

import static com.mongodb.client.model.Filters.*;


/**
 * Created by 石头哥哥 on 1/8/16.
 * <p>
 * mongo_test
 * <p>
 * com.cl.mongo
 * <p>
 * comments:
 * <p>
 * <p>
 * 测试   ::http://jcs130.iteye.com/blog/2236163
 */
@SuppressWarnings("Duplicates")
public class TestMongondb {

    /**
     * @param args
     */
    @SuppressWarnings({"Since15", "unchecked"})
    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("127.0.0.1", 27017);
        MongoDatabase database = mongoClient.getDatabase("test0");//

        UserVo.Builder builder = UserVo.newBuilder();
        builder.setUsername("石头哥哥");


//        CodecRegistry codecRegistry= CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(MongoClient.getDefaultCodecRegistry(),new SelfCodec()));
        //get connetion
//        MongoCollection<Document> documentMongoCollection = database.getCollection("t_user").withCodecRegistry(codecRegistry);

        MongoCollection<Document> documentMongoCollection = database.getCollection("t_user");

        //find  all
        FindIterable<Document> documents = documentMongoCollection.find();
        for (Document document : documents) {
            Object o = document.get("user");
            if (o == null) continue;
            byte[] data = ((Binary) document.get("user")).getData();
            try {
                UserVo userVo = UserVo.parseFrom(data);
                System.out.println(document.getObjectId("_id").getDate());
                System.out.println(userVo.toString());
                System.out.println(document.toJson());
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        }


        FindIterable<Document> iterable_user0 = documentMongoCollection.find(Filters.or(new Document("value", "石头哥哥"), Filters.gt("value", "石头哥哥")));
        for (Document document : iterable_user0) {
            byte[] data = ((Binary) document.get("user")).getData();
            try {
                UserVo userVo = UserVo.parseFrom(data);
                System.out.println(document.getObjectId("_id").getDate());
                System.out.println(userVo.toString());
                System.out.println(document.getString("value"));
                System.out.println(document.toJson());
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        }


        //update
        documentMongoCollection.findOneAndUpdate(eq("value", "石头哥哥"), new Document("$set", new Document("value", "abcdefg")));

        iterable_user0 = documentMongoCollection.find(or(new Document("value", "abcdefg"), gt("value", "abcdefg")));
        for (Document document : iterable_user0) {
            byte[] data = ((Binary) document.get("user")).getData();
            try {
                UserVo userVo = UserVo.parseFrom(data);
                System.out.println(document.getObjectId("_id").getDate());
                System.out.println(userVo.toString());
                System.out.println(document.getString("value"));
                System.out.println(document.toJson());
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        }


        Document document = new Document();
        //binary
        document.append("user", builder.build().toByteArray())//user ---- pb serilal byte array
                .append("value", "石头哥哥");
        //insert
        documentMongoCollection.insertOne(document);
        //creaateIndex
//        documentMongoCollection.createIndex();
        for (Document _d : documentMongoCollection.find()) {
            System.out.println("before:" + _d.toJson());
        }
        //true if a new document should be inserted if there are no matches to the query filter
        documentMongoCollection.updateOne(eq("value", "石头哥哥"), new Document("$set", new Document("value", "这是mongodb测试")));

        for (Document _d : documentMongoCollection.find()) {
            System.out.println(_d.toJson());
        }

        documentMongoCollection.find(new Document("value", "xxxxx")).forEach(new Block<Document>() {
            @Override
            public void apply(Document document) {
                System.out.println("find document....");
                System.out.println(document.getString("value"));
            }
        });


        //delete
        DeleteResult deleteResult = documentMongoCollection.deleteMany(eq("value", 100));
        System.out.println(deleteResult.getDeletedCount());


        // 对输出文档进行排序,-1为递减，1为递增
        // 官方文档的例子有误：http://mongodb.github.io/mongo-java-driver/3.0/driver/getting-started/quick-tour/#sorting-documents
        Document myDoc = documentMongoCollection.find(Filters.exists("value")).sort(new Document("value", -1)).first();
        if (myDoc != null)
            System.out.println(myDoc.toJson());


        /*************************  update 修改数据库中数据 *************************************/

        // 修改时的参数：
        // $inc 对指定的元素加
        // $mul 乘
        // $rename file
        // $setOnInsert 如果以前没有这个元素则增加这个元素，否则不作任何更改
        // $set 修改制定元素的值
        // $unset 移除特定的元素
        // $min 如果原始数据更大则不修改，否则修改为指定的值
        // $max 与$min相反
        // $currentDate 修改为目前的时间

        // //修改第一个符合条件的数据
        // $set 为修改
        documentMongoCollection.updateOne(eq("i", 10), new Document("$set", new Document("i", 110)));
        // 获取全部文档,可以看到以前10的地方变成了110
        for (Document cur : documentMongoCollection.find()) {
            System.out.println(cur.toJson());
        }

        // 批量修改数据并且返回修改的结果，讲所有小于100的结果都加100
        UpdateResult updateResult = documentMongoCollection.updateMany(lt("i", 100),new Document("$inc", new Document("i", 100)));
        System.out.println(updateResult.getModifiedCount());
        // 获取全部文档,可以看到除了刚才修改的110其他的全为了100
        for (Document cur : documentMongoCollection.find()) {
            System.out.println(cur.toJson());
        }

        /************************** 删除数据 *****************************/
        // 删除第一个符合条件的数据
        documentMongoCollection.deleteOne(eq("i", 110));
        // 获取全部文档,可以看到没有110这个数了
        for (Document cur : documentMongoCollection.find()) {
            System.out.println(cur.toJson());
        }

        // 删除所有符合条件的数据，并且返回结果
        deleteResult = documentMongoCollection.deleteMany(gte("i", 100));
        System.out.println(deleteResult.getDeletedCount());
        for (Document cur : documentMongoCollection.find()) {
            System.out.println(cur.toJson());
        }

        /*************************** 程序块，一次执行多条语句 ********************************/
        // 按照语句先后顺序执行
        ArrayList<WriteModel<Document>> list = new ArrayList<>();
        list.add(new UpdateOneModel<Document>(eq("_id", 4),
                new Document("$set", new Document("value", "xxoo"))));// update
        documentMongoCollection.bulkWrite(list);

        // 获取全部文档
        for (Document cur : documentMongoCollection.find()) {
            System.out.println(cur.toJson());
        }

    }
}
